package top.went.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.went.db.dao.DeliverGoodsDao;
import top.went.db.dao.OrderDeliverDetail;
import top.went.db.mapper.DeliverDetailMapper;
import top.went.db.mapper.SendGoodsMapper;
import top.went.exception.NotFoundException;
import top.went.exception.ServiceException;
import top.went.pojo.*;
import top.went.utils.CodeGenerator;
import top.went.vo.*;

import java.math.BigDecimal;
import java.sql.Date;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 发货
 */
@Service
@Transactional(value = "transactionManager",rollbackFor = ServiceException.class)
public class WarehouseSend {
    @Autowired
    private ProductService productService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private SendGoodsMapper sendGoodsMapper;
    @Autowired
    private DeliverDetailMapper deliverDetailMapper;
    @Autowired
    private DeliverGoodsDao deliverGoodsDao;
    @Autowired
    private OrderDeliverDetail detailDao;
    @Autowired
    private WareHouseService wareHouseService;
    @Autowired
    private WareHouseOutIn wareHouseOutIn;

    /** 表格排序*/
    private static Map<String,String> map = new HashMap<>();
    static {
        map.put("dgDate","dg_Date");
        map.put("orderTitle","orderTitle");
        map.put("cusName","cusName");
        map.put("status","status");
        map.put("dgNumber","dg_number");
        map.put("ddDate","dd_Date");
        map.put("ddNumber","dd_Number");
    }


    /**
     * 加载所有发货单
     * @param search
     * @return
     */
    public PageEntity<SendGoodsVo> findSend(SendGoodsSearch search) {
        if (search == null)
            return new PageEntity<SendGoodsVo>(0L,null);
        String order = search.getPage().getSort(map);
        if (order.length() <=0)
            order = "dg_id desc";
        Page<SendGoodsVo> page1 = PageHelper.startPage(search.getPage().getPage(),search.getPage().getSize(),
                order);
        sendGoodsMapper.findAll(search);
        System.out.println(page1);
        return new PageEntity<>(page1.getTotal(), page1.getResult());
    }

    /**
     * 加载发货单
     * @param id
     * @return
     */
    public SendGoodsVo loadOneSend(Long id) throws NotFoundException {
        SendGoodsVo sendGoodsVo = sendGoodsMapper.loadOne(id);
        if (sendGoodsVo == null)
            throw new NotFoundException("发货单不存在");
        return sendGoodsVo;
    }

    /**
     * 加载订单的发货单
     * @param id
     * @return
     */
    public List<SendGoodsVo> loadSendByOrder(Long id){
        return sendGoodsMapper.loadByOrder(id);
    }

    /**
     * 加载所有发货明细
     * @param search
     * @return
     */
    public PageEntity<DeliverDetailEntity> findSend(SendGoodsDetail search) {
        if (search == null)
            return new PageEntity<DeliverDetailEntity>(0L,null);
        String order = search.getPage().getSort(map);
        if (order.length() <=0)
            order = "dd_Id desc";
        Page<DeliverDetailEntity> page1 = PageHelper.startPage(search.getPage().getPage(),search.getPage().getSize(),
                order);
        deliverDetailMapper.findAll(search);
        System.out.println(page1);
        return new PageEntity<>(page1.getTotal(), page1.getResult());
    }

    /**
     * 加载发货明细
     * @param id
     * @return
     */
    public List<DeliverDetailEntity> loadDetailSend(Long id){
        return deliverDetailMapper.loadDetail(id);
    }

    /**
     * 加载发货明细
     * @param id
     * @return
     */
    public List<DeliverDetailVo> loadDetailSendByOrder(Long id){
        return deliverDetailMapper.loadDetailByorder(id);
    }
    /**
     * 通过客户加载发货明细
     * @param id
     * @return
     */
    public List<DeliverDetailVo> loadDetailSendByCus(Long id){
        return deliverDetailMapper.loadDetailByCus(id);
    }

    /**
     * 加载发货单
     * @param id
     * @return
     * @throws NotFoundException
     */
    public DeliverGoodsEntity loadOneDeliver(Integer id) throws NotFoundException {
        DeliverGoodsEntity deliverGoodsEntity = deliverGoodsDao.findOne(false,id);
        if (deliverGoodsEntity == null)
            throw new NotFoundException("发货单不存在");
        return deliverGoodsEntity;
    }

    /**
     * 通过客户加载发货单
     * @param id
     * @return
     */
    public List<SendGoodsVo> loadSendByCus(Long id){
        return sendGoodsMapper.loadSendByCus(id);
    }
    /**
     * 修改发货单
     * @param goodsEntity
     */
    public void modifyDeliver(DeliverGoodsEntity goodsEntity) throws NotFoundException, ServiceException {
        DeliverGoodsEntity deliverGoodsEntity = loadOneDeliver(goodsEntity.getDgId());
        modifyDeliverData(deliverGoodsEntity,goodsEntity);
        if (goodsEntity.getTbAddressByAddressId() != null &&deliverGoodsEntity.getTbAddressByAddressId()!=null)
            modifyDeliverAddress(deliverGoodsEntity.getTbAddressByAddressId(),goodsEntity.getTbAddressByAddressId());
        if (deliverGoodsEntity.getTbAddressByAddressId() == null && goodsEntity.getTbAddressByAddressId()!=null)
            deliverGoodsEntity.setTbAddressByAddressId(goodsEntity.getTbAddressByAddressId());
        try {
            deliverGoodsDao.save(deliverGoodsEntity);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("修改发货单失败");
        }
    }

    /**
     * 修改发货地址
     * @param tbAddressByAddressId
     * @param tbAddressByAddressId1
     */
    private void modifyDeliverAddress(AddressEntity tbAddressByAddressId, AddressEntity tbAddressByAddressId1) {
        tbAddressByAddressId.setAddressName(tbAddressByAddressId1.getAddressName());
        tbAddressByAddressId.setAddressTel(tbAddressByAddressId1.getAddressTel());
        tbAddressByAddressId.setAddressProvince(tbAddressByAddressId1.getAddressProvince());
        tbAddressByAddressId.setAddressCity(tbAddressByAddressId1.getAddressCity());
        tbAddressByAddressId.setAddressCounty(tbAddressByAddressId1.getAddressCounty());
        tbAddressByAddressId.setAddressContent(tbAddressByAddressId1.getAddressContent());
        tbAddressByAddressId.setAddressCode(tbAddressByAddressId1.getAddressCode());
    }

    /**
     * 修改发货单数据
     * @param deliverGoodsEntity
     * @param goodsEntity
     */
    private void modifyDeliverData(DeliverGoodsEntity deliverGoodsEntity, DeliverGoodsEntity goodsEntity) {
        deliverGoodsEntity.setDgDate(goodsEntity.getDgDate());
        deliverGoodsEntity.setDgModel(goodsEntity.getDgModel());
        if (deliverGoodsEntity.getStatus() == 2 || deliverGoodsEntity.getStatus() == 3)
            deliverGoodsEntity.setStatus(goodsEntity.getStatus() ==2 || goodsEntity.getStatus()==3?goodsEntity.getStatus():2);
        deliverGoodsEntity.setDgPkgNumber(goodsEntity.getDgPkgNumber());
        deliverGoodsEntity.setDgWeight(goodsEntity.getDgWeight());
        deliverGoodsEntity.setDgLogistice(goodsEntity.getDgLogistice());
        deliverGoodsEntity.setDgLogisticId(goodsEntity.getDgLogisticId());
        deliverGoodsEntity.setDgFreight(goodsEntity.getDgFreight());
        deliverGoodsEntity.setDgFreightModal(goodsEntity.getDgFreightModal());
        deliverGoodsEntity.setDgOther(goodsEntity.getDgOther());
    }

    /**
     * 通过出库单发货
     * @param id
     * @throws NotFoundException
     * @throws ServiceException
     */
    public void sendGoodsByPull(Integer id,UserEntity userEntity) throws NotFoundException, ServiceException {
        WhPullEntity whPullEntity = wareHouseService.loadOut(id);
        if (whPullEntity.getWpullStatus() == 0)
            throw new ServiceException("该出库单未出库");
        if (whPullEntity.getWpullStatus() > 1)
            throw new ServiceException("该出库单已经发货");
        if (whPullEntity.getTbOrderByOrderId() == null)
            throw new ServiceException("只有订单需要发货");
        DeliverGoodsEntity deliverGoodsEntity = deliverGoodsDao.findOneByPull(false,id);
        sendGoods(deliverGoodsEntity.getDgId(),userEntity);
    }
    /**
     * 通过出库单撤销发货
     * @param id
     * @throws NotFoundException
     * @throws ServiceException
     */
    public void cancelSendGoodsByPull(Integer id) throws NotFoundException, ServiceException {
        WhPullEntity whPullEntity = wareHouseService.loadOut(id);
        if (whPullEntity.getWpullStatus() == 0)
            throw new ServiceException("该出库单未出库");
        DeliverGoodsEntity deliverGoodsEntity = deliverGoodsDao.findOneByPull(false,id);
        cancelSend(deliverGoodsEntity.getDgId());
    }
    /**
     * 发货
     * @param id
     */
    public void sendGoods(Integer id,UserEntity userEntity) throws NotFoundException, ServiceException {
        DeliverGoodsEntity deliverGoodsEntity = loadOneDeliver(id);
        deliverGoodsEntity.setTbUserByUserId(userEntity);
        canSend(deliverGoodsEntity);
        deliverGoodsEntity.setStatus(2);
        deliverGoodsEntity.setDgNumber(CodeGenerator.orderGenerator(false));
        try {
            WhPullEntity whPullEntity = deliverGoodsEntity.getTbWhPullByWpullId();
            whPullEntity.setWpullStatus(2);
            deliverGoodsDao.send(id);
            deliverGoodsDao.save(deliverGoodsEntity);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("发货失败");
        }
    }

    /**
     * 是否可以发货
     * @param deliverGoodsEntity
     * @throws ServiceException
     */
    private void canSend(DeliverGoodsEntity deliverGoodsEntity) throws ServiceException {
        if (deliverGoodsEntity.getStatus() != 1)
            throw new ServiceException("该发货单已经发货");
        if (deliverGoodsEntity.getTbDeliverDetailsByDgId() == null
                || deliverGoodsEntity.getTbDeliverDetailsByDgId().size()<=0)
            throw new ServiceException("发货单中没有产品");
        AddressEntity addressEntity = deliverGoodsEntity.getTbAddressByAddressId();
        if (!haveAddress(addressEntity)){
            deliverGoodsEntity.setTbAddressByAddressId(deliverGoodsEntity.
                    getTbWhPullByWpullId().getTbOrderByOrderId().getTbAddressByAddressId());
            if (!haveAddress(deliverGoodsEntity.getTbAddressByAddressId()))
                throw new ServiceException("请输入地址信息");
        }
        if (deliverGoodsEntity.getDgLogisticId() == null)
            throw new ServiceException("请输入物流单号");
    }

    /**
     * 判断发货单是否有地址信息
     * @param addressEntity
     * @return
     * @throws ServiceException
     */
    private boolean haveAddress(AddressEntity addressEntity) {
        if (addressEntity == null || addressEntity.getAddressName() == null ||( ( addressEntity.getAddressProvince() == null
                || addressEntity.getAddressCity() == null) && addressEntity.getAddressCode()==null))
            return false;
        return true;
    }

    /**
     * 取消发货
     * @param id
     * @throws ServiceException
     * @throws NotFoundException
     */
    public void cancelSend(Integer id) throws ServiceException, NotFoundException {
        DeliverGoodsEntity deliverGoodsEntity = loadOneDeliver(id);
        if (deliverGoodsEntity.getStatus() == 1)
            throw new ServiceException("该发货单没有发货");
        if (deliverGoodsEntity.getStatus() == 3)
            throw new ServiceException("该发货单商品已经被签收");
        ///判断有没有未完成退货
        deliverGoodsEntity.setStatus(1);
        try {
            WhPullEntity whPullEntity = deliverGoodsEntity.getTbWhPullByWpullId();
            whPullEntity.setWpullStatus(1);
            deliverGoodsDao.cancelSend(id);
            deliverGoodsDao.save(deliverGoodsEntity);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("撤销发货失败");
        }
    }

    /**
     * 删除发货单
     * @throws NotFoundException
     * @throws ServiceException
     */
    public void deleteSend(WhPullEntity whPullEntity) throws NotFoundException, ServiceException {
        DeliverGoodsEntity deliverGoodsEntity = deliverGoodsDao.findOneByPull(false,whPullEntity.getWpullId());
        if (deliverGoodsEntity != null && deliverGoodsEntity.getStatus() != 1)
            throw new ServiceException("已经发货的发货单不能删除");
        deliverGoodsEntity.setLogicDelete(true);
        try {
            deliverGoodsDao.deleteSend(deliverGoodsEntity.getDgId());
            deliverGoodsDao.save(deliverGoodsEntity);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("删除发货单失败");
        }
    }

    /**
     * 添加交付记录
     * @param deliverDetailEntity
     * @throws NotFoundException
     * @throws ServiceException
     */
    public void addOneSend(DeliverDetailEntity deliverDetailEntity) throws NotFoundException, ServiceException {
        ProductFormatEntity formatEntity = productService.load(deliverDetailEntity.getFormatEntity().getPfId());
        OrderEntity orderEntity = orderService.load(deliverDetailEntity.getTbOrderByOrderId().getOrderId().longValue());
        if (orderEntity.getOrderType())
            throw new ServiceException("请选择合同");
        deliverDetailEntity.setStatus(1);
        deliverDetailEntity.setFormatEntity(formatEntity);
        deliverDetailEntity.setTbCustomerByCusId(orderEntity.getTbCustomerByCusId());
        deliverDetailEntity.setTbDeliverGoodsByDgId(null);
        deliverDetailEntity.setDdPrice(formatEntity.getPfPrice());
        deliverDetailEntity.setDdCost(deliverDetailEntity.getDdTotal().subtract(deliverDetailEntity.getDdPrice().
                multiply(BigDecimal.valueOf(deliverDetailEntity.getDdNumber()))));
        try {
            detailDao.save(deliverDetailEntity);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("添加交付记录失败");
        }
    }
    /**
     * 出库单出库自动生成发货单
     * @param whPullEntity
     * @throws NotFoundException
     * @throws ServiceException
     */
    public void addSend(WhPullEntity whPullEntity) throws NotFoundException, ServiceException {
        //加上管理员
        DeliverGoodsEntity deliverGoodsEntity = new DeliverGoodsEntity(Date.valueOf(LocalDate.now()),
                CodeGenerator.orderGenerator(false),false,1,
                whPullEntity.getTbOrderByOrderId().getTbAddressByAddressId(),
                null,whPullEntity);
        List<DeliverDetailEntity> deliverDetailEntities = new ArrayList<>();
        buildSends(deliverGoodsEntity,whPullEntity.getWpullId(), whPullEntity, deliverDetailEntities);
        try {
            detailDao.save(deliverDetailEntities);
            deliverGoodsDao.save(deliverGoodsEntity);
        }catch (Exception e){
            e.printStackTrace();
            throw new ServiceException("新建发货单失败");
        }
    }

    /**
     * 发货明细数据
     *
     * @param deliverGoodsEntity
     * @param pullId
     * @param whPullEntity
     * @param deliverDetailEntities
     * @throws ServiceException
     */
    private void buildSends(DeliverGoodsEntity deliverGoodsEntity, Integer pullId, WhPullEntity whPullEntity,
                            List<DeliverDetailEntity> deliverDetailEntities)
            throws ServiceException {
        List<WpDetailEntity> wpDetailEntities = wareHouseOutIn.loadAllDetail(0,pullId);
        if (wpDetailEntities == null || wpDetailEntities.size() <=0)
            throw new ServiceException("出库单错误");
        for (WpDetailEntity wpDetailEntity : wpDetailEntities) {
            DeliverDetailEntity deliverDetailEntity = new DeliverDetailEntity(
                    wpDetailEntity.getOutNumber(),wpDetailEntity.getWdTotal(),
                    Date.valueOf(LocalDate.now()),wpDetailEntity.getWdCost(),
                    wpDetailEntity.getWdPrice(),wpDetailEntity.getWdOther(),
                    0,wpDetailEntity.getTbProductFormatByPfId(),
                    wpDetailEntity.getTbCustomerByCusId(),
                    whPullEntity.getTbOrderByOrderId(),deliverGoodsEntity
            );
            deliverDetailEntities.add(deliverDetailEntity);
        }
    }
}
